//
//  HttpResponse.cpp
//  EZC_Library
//
//  Created by ellzu on 14-9-23.
//  Copyright (c) 2014年 ellzu. All rights reserved.
//

#include "HttpResponse.h"
#include "HttpRequest.h"

using namespace EZHttp;

HttpResponse::HttpResponse()
{
    _responseCode = 0;
    _bufferLen = 0;
    _buffer = 0;
    _writeBufferOil = 0;
    _contentLen = 0;
    _request = 0;
    _fileHandel = 0;
}

HttpResponse::~HttpResponse()
{
    this->closeFileHandel();
}

int HttpResponse::responseCode()
{
    return _responseCode;
}
void HttpResponse::setResponseCode(int code)
{
    _responseCode = code;
}

std::vector<std::string>* HttpResponse::headers()
{
    return &_headers;
}

void HttpResponse::setBufferLen(size_t len)
{
    unsigned char *nTemp = 0;
    if (len > 0) {
        nTemp = new unsigned char[len];
        memset(nTemp, 0, (size_t)len);
        size_t copyLen = len > _bufferLen ? _bufferLen : len;
        
        if (copyLen>0) {
            memcpy(nTemp, _buffer, copyLen);
        }
    }
    
    if (_buffer) {
        delete _buffer;
        _buffer = 0;
    }
    _writeBufferOil = _writeBufferOil>len? len:_writeBufferOil;
    _buffer = nTemp;
    _bufferLen = len;
    
}

size_t HttpResponse::appendBuffer(unsigned char* buffer,size_t bufferLen)
{
    size_t writeLen = 0;
    if (_fileHandel!=0) { // save to file
        
        fseek(_fileHandel, 0, SEEK_END);
        writeLen = fwrite(buffer, 1, bufferLen, _fileHandel);
        _writeBufferOil += writeLen;
        
        if (_writeBufferOil==_contentLen) {
            fflush(_fileHandel);
            if (_request->downLoadPath().length() > 0) {
                rename(_request->tempPath().c_str(), _request->downLoadPath().c_str());
            }
        }
    }else{
        if (_writeBufferOil+bufferLen > _bufferLen) {
            size_t newBufferLen = ( (_writeBufferOil+bufferLen)/1024 + ((_writeBufferOil+bufferLen)%1024==0?0:1) )*1024;
            newBufferLen = (_contentLen<1024*10 && newBufferLen < _contentLen)? _contentLen:newBufferLen;
            setBufferLen(newBufferLen);
        }
        memcpy(_buffer+_writeBufferOil, buffer, bufferLen);
        _writeBufferOil+=bufferLen;
        writeLen = bufferLen;
        if (_writeBufferOil == _contentLen && _request->downLoadPath().length()>0 ) { // save to download file
            FILE *tempFile = fopen(_request->downLoadPath().c_str(), "wb");
            if (tempFile) {
                fwrite(_buffer, 1, _writeBufferOil, tempFile);
                fflush(tempFile);
                fclose(tempFile);
            }
        }
    }
    
    
    return writeLen;
}


void HttpResponse::setContentLen(size_t len)
{
    if (_contentLen == len) {
        return;
    }
    _contentLen = len;
    
    this->closeFileHandel();
    
    if (_contentLen!=0) {
        this->tryOpenFileHandel();
    }
}
size_t HttpResponse::contentLen()
{
    return _contentLen;
}


FILE* HttpResponse::tryOpenFileHandel()
{
    if (_fileHandel==0) {
        std::string filePath = _request->tempPath();
        if (filePath.length()>0) {
            _fileHandel = fopen(filePath.c_str(), "wb+");
        }
    }
    return _fileHandel;
}
void HttpResponse::closeFileHandel()
{
    if (_fileHandel) {
        fclose(_fileHandel);
        _fileHandel = 0;
    }
}

HttpRequest* HttpResponse::request()
{
    return _request;
}
void HttpResponse::setRequest(HttpRequest *request)
{
    _request = request;
}

unsigned char* HttpResponse::content()
{
    return _buffer;
}
size_t HttpResponse::contentCurLen()
{
    return _writeBufferOil;
}
size_t HttpResponse::copyContent(unsigned char*buffer,size_t bufferLen,size_t offset)
{
    if (offset>_writeBufferOil) {
        return 0;
    }
    size_t hasLen = _writeBufferOil - offset;
    size_t willCopyLen = hasLen > bufferLen? bufferLen:hasLen;
    
    if (_fileHandel) {
        fseek(_fileHandel, offset, SEEK_SET);
        size_t readLen = fread(buffer, willCopyLen, 1, _fileHandel);
        int a = readLen;
    }else{
        memcpy(buffer, _buffer+offset, willCopyLen);
    }
    
    return willCopyLen;
}



